home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / MISC / DTMFF110 / SC_SB16.C < prev    next >
C/C++ Source or Header  |  1997-08-05  |  6KB  |  246 lines

  1. /*
  2.  *  Routines for sampling from a Soundblaster-16 sound card.
  3.  *  These routines require the functions in sbio.c derived from
  4.  *  Ethan Brodsky's Soundblaster-16 programming library .
  5.  *  Copyright (C) 1997    Philip VanBaren & Emil Laurentiu
  6.  *  Last modified: Wednesday, 06 August 1997
  7.  */
  8.  
  9. #include "freq.h"
  10.  
  11. #ifdef SC_SB16
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <math.h>
  16. #include <mem.h>
  17. #include <graphics.h>
  18. #include "sb.h"
  19. #include "sbio.h"
  20. #include "extern.h"
  21.  
  22. /* Function prototypes */
  23. int          atox16( char *ptr );
  24. void interrupt sb16_callback( void );
  25. void          init_sb16( char **environ );
  26. void          reset_sb16( void );
  27. void          halt_sb16( void );
  28. void          cleanup_sb16( void );
  29. void          recordblock_sb16( void far * buffer );
  30. void          set_mixer_sb16( int mix, int level );
  31.  
  32. int
  33. atox16( char *ptr )
  34. {
  35.   // Convert ascii hex values to integer
  36.   int        v = 0;
  37.  
  38.   while ( ( ( *ptr >= '0' ) && ( *ptr <= '9' ) ) || ( ( ( *ptr | 0x20 ) >= 'a' ) && ( ( *ptr | 0x20 ) <= 'f' ) ) )
  39.   {
  40.     v = v * 16;
  41.     if ( *ptr <= '9' )
  42.       v = v + *ptr - '0';
  43.     else
  44.       v = v + ( *ptr | 0x20 ) - 'a' + 10;
  45.     ptr++;
  46.   }
  47.   return v;
  48. }
  49.  
  50. #define is_blaster(var) ((((var)[0]=='B')||((var)[0]=='b')) && \
  51.              (((var)[1]=='L')||((var)[1]=='l')) && \
  52.              (((var)[2]=='A')||((var)[2]=='a')) && \
  53.              (((var)[3]=='S')||((var)[3]=='s')) && \
  54.              (((var)[4]=='T')||((var)[4]=='t')) && \
  55.              (((var)[5]=='E')||((var)[5]=='e')) && \
  56.              (((var)[6]=='R')||((var)[6]=='r')))
  57.  
  58. /* Turn off stack checking for this routine */
  59. #pragma option -N-
  60. void          interrupt
  61. sb16_callback(    )
  62. {
  63.   extern int    poll16port, dma_maskport, dma_stopmask;
  64.   unsigned int far *s, far * d;
  65.   int        i;
  66.  
  67.   /*
  68.    * Callback function.     This function is called every time a buffer has been
  69.    * filled.  It copies the latest data, and sets a flag so the main loop
  70.    * recognises and processes the buffer.
  71.    */
  72.   d = buffer[record_buffer];
  73.   s = dmaptr + (curblock * fftlen);
  74.   for ( i = 0; i < fftlen; i++ )
  75.     *d++ = *s++;
  76.   flag[record_buffer] = 1;
  77.   if ( ++record_buffer >= BUFFERS )
  78.     record_buffer = 0;
  79.  
  80.   curblock = !curblock;        /* Toggle active block flag */
  81.   /* If we hit the end of the queued buffers, stop recording */
  82.   if ( record_buffer == queue_buffer )
  83.   {
  84.     write_dsp( 0xD5 );        /* Stop digitized sound xfer     */
  85.     outportb( dma_maskport, dma_stopmask );    /* Mask DMA channel         */
  86.     sb16dmarunning = 0;
  87.   }
  88.   /* Acknowledge the interrupt */
  89.   inportb( poll16port );
  90.   outportb( 0x20, 0x20 );
  91.   outportb( 0xA0, 0x20 );
  92. }
  93.  
  94. /* Restore stack checking to the command-line specified state */
  95. #pragma option -N.
  96.  
  97.  
  98. void
  99. init_sb16( char **environ )
  100. {
  101.   int        i;
  102.   // Scan the environment variables for BLASTER=Axxx Ix Dx
  103.   for ( i = 0; environ[i] != NULL; i++ )
  104.   {
  105.     if ( is_blaster( environ[i] ) )
  106.     {
  107.       int        j;
  108.       DOUT( "SB16: Found the BLASTER environment variable:" );
  109.       DOUT( environ[i] );
  110.       for ( j = 8; environ[i][j] != 0; j++ )
  111.       {
  112.     if ( ( environ[i][j] == 'A' ) || ( environ[i][j] == 'a' ) )
  113.     {
  114.       DOUT( "SB16: Axxx found" );
  115.       sb_addr = atox16( &environ[i][j + 1] );
  116.     }
  117.     if ( ( environ[i][j] == 'H' ) || ( environ[i][j] == 'h' ) )
  118.     {
  119.       DOUT( "SB16: Hx found" );
  120.       sb_dma = atoi( &environ[i][j + 1] );
  121.     }
  122.     if ( ( environ[i][j] == 'I' ) || ( environ[i][j] == 'i' ) )
  123.     {
  124.       DOUT( "SB16: Ix found" );
  125.       sb_irq = atoi( &environ[i][j + 1] );
  126.     }
  127.     // Skip to the next parameter
  128.     while ( ( environ[i][j] != ' ' ) && ( environ[i][j + 1] != 0 ) )
  129.       j++;
  130.       }
  131.       break;
  132.     }
  133.   }
  134. #ifdef DEBUG_OUTPUT
  135.   {
  136.     char      message[100];
  137.     sprintf( message, "SB16: Address=0x%03x, DMA=%d, IRQ=%d", sb_addr, sb_dma, sb_irq );
  138.     DOUT( message );
  139.   }
  140. #endif
  141.   /* Set up the pointers to the recording routines */
  142.   reset_soundcard = reset_sb16;
  143.   halt_soundcard = halt_sb16;
  144.   cleanup_soundcard = cleanup_sb16;
  145.   recordblock = recordblock_sb16;
  146.   set_mixer = set_mixer_sb16;
  147.   sample_size = 16;
  148.   mixers = 1;
  149.  
  150.   DOUT( "SB16: Initializing the card" );
  151.  
  152.   if ( !init_sb( sb_addr, sb_irq, sb_dma, input, MAX_LEN ) )
  153.   {
  154.     closegraph(     );
  155.     puts( "Unable to initialize the Soundblaster16 card, aborting..." );
  156.     exit( 1 );
  157.   }
  158.   DOUT( "SB16: Reading initial mixer settings" );
  159.   mic_level = get_mic_level(  );
  160.   ext_level = get_line_level(  );
  161.   int_level = get_cd_level(  );
  162.   DOUT( "SB16: Set Master volume & FM volume to maximum" );
  163.   set_master_level( 0x0f );
  164.   set_fm_level( 0x0f );
  165. }
  166.  
  167. void
  168. reset_sb16( void )
  169. {
  170.   int        i;
  171.   /* Round sampling rate to a valid value for the SB card */
  172.   i = floor( 1000000.0 / SampleRate + 0.5 );
  173.   if ( i < 1 )
  174.     i = 1;
  175.   SampleRate = floor( 1000000.0 / ( double ) i + 0.5 );
  176.  
  177.   /* Reset the buffer pointers */
  178.   queue_buffer = 0;        // Pointer to next buffer to be queued
  179.   record_buffer = 0;        // Pointer to next buffer to be filled
  180.   process_buffer = 0;        // Pointer to next buffer to be FFTed
  181.  
  182.   for ( i = 0; i < BUFFERS; i++ )
  183.     flag[i] = 0;
  184.  
  185.   /* This function starts the DMA process. */
  186.   DOUT( "SB16: Starting the recording process" );
  187.   recordblock_sb16( ( char far * ) buffer[queue_buffer] );
  188. }
  189.  
  190. void
  191. halt_sb16( void )
  192. {
  193.   /*
  194.    * Shut down the DMA system.
  195.    */
  196.   DOUT( "SB16: Stopping the sampling process" );
  197.   stopio(  );
  198. }
  199.  
  200. void
  201. cleanup_sb16( void )
  202. {
  203.   /*
  204.    * Shut down the DMA system and remove the interrupt handler.
  205.    */
  206.   DOUT( "SB16: Stopping the sampling process and cleaning up" );
  207.   shutdown_sb(    );
  208.   Sb_FM_Reset(    );
  209. }
  210.  
  211. void
  212. recordblock_sb16( void far * buffer )
  213. {
  214.   /* Start transferring data into the DMA buffer */
  215.   if ( ++queue_buffer >= BUFFERS )
  216.     queue_buffer = 0;
  217.   /* If the DMA has halted, restart it */
  218.   if ( !sb16dmarunning )
  219.     startio( ( unsigned int ) SampleRate, fftlen );
  220. }
  221.  
  222. void
  223. set_mixer_sb16( int mix, int level )
  224. {
  225.   /*
  226.    * Set a mixer level on the PAS16 card
  227.    */
  228.   if ( mix == MIXER_EXT )
  229.   {
  230.     DOUT( "SB16: Setting the line mixer level" );
  231.     set_line_level( level );
  232.   }
  233.   else if ( mix == MIXER_INT )
  234.   {
  235.     DOUT( "SB16: Setting the CD mixer level" );
  236.     set_cd_level( level );
  237.   }
  238.   else if ( mix == MIXER_MIC )
  239.   {
  240.     DOUT( "SB16: Setting the microphone mixer level" );
  241.     set_mic_level( level );
  242.   }
  243. }
  244.  
  245. #endif
  246.